//Town 0
begintownscript;

variables;
int i,j,k,m,n,q,r,x,y;
int a,b,c,d;
string str;
body;

beginstate INIT_STATE;
break;

beginstate EXIT_STATE;
break;

beginstate START_STATE;
	if(get_flag(0,3) == 120){ //this is the final level
		//check for living doomguards
		a=0; //whether a doomguard has been found
		i=6; //creature number
		while(i<120){
			if((char_ok(i) == 1) && (creature_type(i) == 75)){
				a = 1;
				i = 1000; //break out of the loop
			}
			i = i + 1;
		}
		if((a == 0) && has_item(445)){ //if all doomguards are dead
			set_state_continue(98);
		}
	}
	//check for living, hostile creatures
	a=0; //whether a live enemy has been found
	i=6; //creature number
	while(i<120){
		if((char_ok(i) == 1) && (char_attitude_to_char(i,0) == 2)){
			a = 1;
			i = 1000; //break out of the loop
		}
		i = i + 1;
	}
	if(a == 0) //only activate training if no enemies remain
		turn_off_training(0);
	else
		turn_off_training(1);
break;

beginstate 10; //dispatcher state
	if(get_flag(0,0) < 24)
		set_state_continue(10+get_flag(0,0));
break;

beginstate 11; //set all floor to 255
	//DEBUGprint_num(11);
	i=0; //location index
	//use this funny kind of loop to save on operations
	while(i < 4096){ 
		set_floor((i % 64), i / 64,255);
		i = i + 1;
	}
	set_flag(0,0,2);
break;

beginstate 12; //set all terrain to zero
	//DEBUGprint_num(12);
	i=0; //location index
	while(i < 4096){
		set_terrain((i % 64), i / 64,0);
		i = i + 1;
	}
	set_flag(0,0,3);
break;

beginstate 13; //create room rectangles
	//rooms are stored in flag columns 1-4
	//room n upper left x is in flag (1,n)
	//upper left y is in (2,n)
	//width is in (3,n)
	//height is in (4,n)
	if(get_flag(0,3) == 119) //special room layout for final level
		set_state_continue(90);
	//DEBUGprint_num(13);
	//choose to create a random number of rooms
	set_flag(0,1,get_ran(1,5,10));
	//create randomized dimensions for each room
	//	rooms must not touch the edge of the town
	//	and should not be smaller than 16 square units
	i=0; //room number
	while(i<get_flag(0,1)){
		set_flag(1,i,get_ran(1,1,60));
		j=60;
		if(get_flag(1,i)==60)
			j=57;
		else if(get_flag(1,i)==59 || get_flag(1,i)==58)
			j=59;
		set_flag(2,i,get_ran(1,1,j));
		//DEBUGprint_nums(i,get_flag(1,i),get_flag(2,i));
		j=10;
		if(10>(63-get_flag(1,i)))
			j=63-get_flag(1,i);
		set_flag(3,i,get_ran(1,3,j));
		j=3;
		if(get_flag(3,i)==3)
			j=6;
		else if(get_flag(3,i)==4 || get_flag(3,i)==5)
			j=4;
		k=10;
		if(10>(63-get_flag(2,i)))
			k=63-get_flag(2,i);
		if(j>k)
			j = k - 1;
		set_flag(4,i,get_ran(1,j,k));
		i=i+1;
	}
	set_flag(0,0,4);
break;

beginstate 14; //draw floors for rooms
	//DEBUGprint_num(14);
	i=0; //room number
	while(i < get_flag(0,1)){
		j=get_flag(1,i);
		//draw the rectangle of floor
		while(j < (get_flag(1,i)+get_flag(3,i))){
			k=get_flag(2,i);
			while(k < (get_flag(2,i)+get_flag(4,i))){
				set_floor(j,k,4);
				k=k +1;
			}
			j=j +1;
		}
		i=i +1;
	}
	set_flag(0,0,5);
break;

beginstate 15; //draw floors for hallways
	//DEBUGprint_num(15);
	i = 1; //room number, skipping first room
	while(i < get_flag(0,1)){
		if(i>0) //connect every room to a lower numbered room
			//  this insures that all rooms connect
			j = get_ran(1,0,i - 1);
		else //just in case
			j = 0;
		if(get_flag(0,3) == 119)
			j = i - 1;
		//debug output
		clear_buffer();
		append_string("connecting room ");
		append_number(i);
		append_string(" to ");
		append_number(j);
		get_buffer_text(str);
		//DEBUGprint_str(str);
		//(a,b) and (c,d) are points in the two rooms that we will connect
		a = get_ran(1,get_flag(1,i),get_flag(1,i) + get_flag(3,i) - 1);
		b = get_ran(1,get_flag(2,i),get_flag(2,i) + get_flag(4,i) - 1);
		c = get_ran(1,get_flag(1,j),get_flag(1,j) + get_flag(3,j) - 1);
		d = get_ran(1,get_flag(2,j),get_flag(2,j) + get_flag(4,j) - 1);
		m = c - a; //the horizontal distance we need to cover
		n = d - b; //the vertical distance we need to cover
		x = a; //the current x coordinate
		y = b; //the current y coordinate
		//while there is distance remaining
		while((m != 0) || (n != 0)){
			//if horizontal distance remains
			if(m != 0){
				//store direction; my kingdom for a ternary operator!
				k=0;
				if(m<0){
					m= -1 * m;
					k=1;
				}
				//go half to all of the remaining distance
				q = get_ran(1,m / 2,m);
				//retrieve direction
				if(k==1){
					m = -1 * m;
					q = -1 * q;
				}
				//draw the segment
				k=x;
				while(k != (x+q)){
					if(q<0) //move in the right direction
						k = k  - 1;
					else
						k = k + 1;
					set_floor(k,y,4);
				}
				//record the distance traversed
				x = x + q;
				m = m - q;
			}
			//if vertical distance remains
			if(n != 0){
				//store direction
				k=0;
				if(n<0){
					n= -1 * n;
					k=1;
				}
				//go half to all of the remaining distance
				q = get_ran(1,n / 2,n);
				//retrieve direction
				if(k==1){
					n = -1 * n;
					q = -1 * q;
				}
				//draw the segment
				k=y;
				while(k != (y+q)){
					if(q<0)
						k = k  - 1;
					else
						k = k + 1;
					set_floor(x,k,4);
				}
				//record the distance traversed
				y = y + q;
				n = n - q;
			}
		}
		i = i + 1;
	}
	set_flag(0,0,6);
break;

beginstate 16; //try to find an exit point in a room or hallway
	//DEBUGprint_num(16);
	if(get_flag(0,3) == 119){ //on the last level
		set_flag(0,2,25);
		set_flag(0,0,8);
		end(); //so don't let the player go down farther
	}
	i = 0; //the number of exit points that have been examined
	j = -1; //the selected exit point
	//start at a random potential exit point so as not to favor lower numbered ones
	k = get_ran(1,0,24);
	while(i < 25){ //stop after going through all 25 possible points
		if(get_floor(get_flag(5,k),get_flag(6,k))!=255){
			j=k;
			i=100;
		}
		k = k + 1;
		if(k == 25) //loop around in case we started somewhere in the middle
			k = 0;
		i = i + 1;
	}
	if(j > -1){//found one that works, so bless it
		//DEBUGprint_nums(j,get_flag(5,j),get_flag(6,j));
		set_terrain(get_flag(5,j),get_flag(6,j),284); //trapdoor
		set_floor(get_flag(5,j),get_flag(6,j),4); //make utterly sure that this space can be stepped on
		set_flag(0,2,j);
		set_flag(0,0,8); //skip the random exit connection state
	}
	else //otherwise just connect in a random exit point
		set_flag(0,0,7);
break;

beginstate 17; //connect a random exit point into the system and bless it
	if(get_flag(0,3) == 119){//on the last level
		set_flag(0,2,25);
		set_flag(0,0,8);
		end(); //so don't let the player go down farther
	}
	//DEBUGprint_num(17);
	i = get_ran(1,0,24); //a random exit point
	set_terrain(get_flag(5,i),get_flag(6,i),284);
	set_floor(get_flag(5,i),get_flag(6,i),4);
	set_flag(0,2,i);
	j = get_ran(1,0,get_flag(0,1) - 1); //a random room
	a = get_flag(5,i); //the x coordinate of the exit point
	b = get_flag(6,i); //the y coordinate of the exit point
	c = get_ran(1,get_flag(1,j),get_flag(1,j) + get_flag(3,j) - 1); //the x coordinate of the point in the room to connect to
	d = get_ran(1,get_flag(2,j),get_flag(2,j) + get_flag(4,j) - 1); //the y coordinate of the point in the room to connect to
	m = c - a; //the horizontal distance we need to cover
	n = d - b; //the vertical distance we need to cover
	x=a; //the current x coordinate
	y=b; //the current y coordinate
	//same method as connecting rooms
	while((m != 0) || (n != 0)){
		if(m != 0){
			k=0;
			if(m<0){
				m= -1 * m;
				k=1;
			}
			q = get_ran(1,m / 2,m);
			if(k==1){
				m = -1 * m;
				q = -1 * q;
			}
			k=x;
			while(k != (x+q)){
				if(q<0)
					k = k  - 1;
				else
					k = k + 1;
				set_floor(k,y,4);
			}
			x = x + q;
			m = m - q;
		}
		if(n != 0){
			k=0;
			if(n<0){
				n= -1 * n;
				k=1;
			}
			q = get_ran(1,n / 2,n);
			if(k==1){
				n = -1 * n;
				q = -1 * q;
			}
			k=y;
			while(k != (y+q)){
				if(q<0)
					k = k  - 1;
				else
					k = k + 1;
				set_floor(x,k,4);
			}
			y = y + q;
			n = n - q;
		}
	}
	set_flag(0,0,8);
break;

beginstate 18; //wall the first quarter of the town
	//DEBUGprint_num(18);
	i = 0; //x coordinate
	while(i < 32){
		j = 0; //y coordinate
		while(j < 32){
			if(get_floor(i,j)==255){
				if((j > 0) && (get_floor(i,j - 1) != 255))//need wall to north
					k = k + 1;
				if(get_floor(i + 1,j) != 255)//need wall to east
					k = k + 2;
				if(get_floor(i,j + 1) != 255)//need wall to south
					k = k + 4;
				if((i>0) && (get_floor(i - 1,j) != 255))//need wall to west
					k = k + 8;
				if(k>0){ //draw the wall
					set_terrain(i,j,420+k);
					k=0;
				}
			}
			j = j + 1;
		}
		i = i + 1;
	}
	set_flag(0,0,9);
break;

beginstate 19; //wall the second quarter of the town
	//DEBUGprint_num(19);
	i = 32; //x coordinate
	while(i < 64){
		j = 0; //y coordinate
		while(j < 32){
			if(get_floor(i,j)==255){
				if((j > 0) && (get_floor(i,j - 1) != 255))//need wall to north
					k = k + 1;
				if((i < 63) && (get_floor(i + 1,j) != 255))//need wall to east
					k = k + 2;
				if(get_floor(i,j + 1) != 255)//need wall to south
					k = k + 4;
				if(get_floor(i - 1,j) != 255)//need wall to west
					k = k + 8;
				if(k>0){ //draw the wall
					set_terrain(i,j,420+k);
					k=0;
				}
			}
			j = j + 1;
		}
		i = i + 1;
	}
	set_flag(0,0,10);
break;

beginstate 20; //wall the third quarter of the town
	//DEBUGprint_num(20);
	i = 0; //x coordinate
	while(i < 32){
		j = 32; //y coordinate
		while(j < 64){
			if(get_floor(i,j)==255){
				if(get_floor(i,j - 1) != 255)//need wall to north
					k = k + 1;
				if(get_floor(i + 1,j) != 255)//need wall to east
					k = k + 2;
				if((j < 63) && (get_floor(i,j + 1) != 255))//need wall to south
					k = k + 4;
				if((i > 0) && (get_floor(i - 1,j) != 255))//need wall to west
					k = k + 8;
				if(k>0){ //draw the wall
					set_terrain(i,j,420+k);
					k=0;
				}
			}
			j = j + 1;
		}
		i = i + 1;
	}
	set_flag(0,0,11);
break;

beginstate 21; //wall the fourth quarter of the town
	//DEBUGprint_num(21);
	i = 32; //x coordinate
	while(i < 64){
		j = 32; //y coordinate
		while(j < 64){
			if(get_floor(i,j)==255){
				if(get_floor(i,j - 1) != 255)//need wall to north
					k = k + 1;
				if((i < 63) && (get_floor(i + 1,j) != 255))//need wall to east
					k = k + 2;
				if((j < 63) && (get_floor(i,j +1 )!=255))//need wall to south
					k = k + 4;
				if(get_floor(i - 1,j) != 255)//need wall to west
					k = k + 8;
				if(k>0){ //draw the wall
					set_terrain(i,j,420+k);
					k=0;
				}
			}
			j = j + 1;
		}
		i = i + 1;
	}
	set_flag(0,0,12);
break;

beginstate 22; //do corner correction for first half of town
	//DEBUGprint_num(22);
	i = 0; //x coordinate
	while(i < 64){
		j = 0; //y coordinate
		while(j<32){
			if((get_floor(i,j) == 255) && (get_terrain(i,j) == 0)){ //if it's inside the walls
				if((i > 0) && (j > 0) && (get_floor(i - 1,j - 1) != 255))
					set_terrain(i,j,407);
				else if((i < 63) && (j > 0) && (get_floor(i + 1,j - 1) != 255))
					set_terrain(i,j,407);
				else if((i> 0) && (get_floor(i - 1,j + 1) != 255))
					set_terrain(i,j,407);
				else if((i < 63) && (get_floor(i + 1,j + 1) != 255))
					set_terrain(i,j,407);
			}
			j = j +1;
		}
		i = i +1;
	}
	set_flag(0,0,13);
break;

beginstate 23; //do corner correction for second half of town
	//DEBUGprint_num(23);
	i = 0; //x coordinate
	while(i < 64){
		j = 32; //y coordinate
		while(j<64){
			if((get_floor(i,j) == 255) && (get_terrain(i,j) == 0)){
				if((i > 0) && (get_floor(i - 1,j - 1) != 255))
					set_terrain(i,j,407);
				else if((i < 63) && (get_floor(i + 1,j - 1) != 255))
					set_terrain(i,j,407);
				else if((i> 0) && (j < 63) && (get_floor(i - 1,j + 1) != 255))
					set_terrain(i,j,407);
				else if((i < 63) && (j < 63) && (get_floor(i + 1,j + 1) != 255))
					set_terrain(i,j,407);
			}
			j = j +1;
		}
		i = i +1;
	}
	set_flag(0,0,14);
break;

beginstate 24; //place enemies
	if(get_flag(0,3) == 119)
		set_state_continue(91);
	//DEBUGprint_num(24);
	i = (get_flag(0,3) / 4) + 1;  //the highest level of monsters to place
	j = i - 3; //the lowest level of monsters to place
	if(j < 1)
		j = 1;
	//DEBUGprint_num(i);
	//DEBUGprint_num(j);
	k = get_ran(1,3,8); //the number of monsters to place
	a = 0; //number of monsters placed
	while(a < k){ //choose k monsters to place
		m = get_ran(1,j,i); //the specific base level of monster to place
		b = 72; //the base creature type
		c =3; //the number of creature types to choose among
		//insanely over-optimized lookup table: 
		if(get_flag(0,3) <= 1)
			c = 1;
		else if((m < 2) || ((m > 11) && (m < 19)) || ((m > 19) && (m < 30)))
			c = 2;
		else if((m == 6) || (m == 7) || (m == 10))
			c = 4;
		if(m < 4)
			b = (2 * m) - 1;
		else if((m == 4) || (m == 5))
			b = (3 * m) - 4;
		else if((m == 6) || (m == 7))
			b = (4 * m) - 10;
		else if((m == 8) || (m == 9))
			b = (3 * m) - 2;
		else if(m == 10)
			b = 28;
		else if(m == 11)
			b = 32;
		else if((m > 11) && (m < 20))
			b = (2 * m) + 11;
		else if((m > 19) && (m < 30))
			b = (6 + m) * 2;
		else if(m == 30)
			b = 72;
		m = get_ran(1,b,b + c - 1); //finally, the type of monster to place
		
		b = get_ran(1,1,get_flag(0,1) - 1); //choose a random room to put the monster in
		//(but not the first room—try to avoid putting monster right next to where the player starts.)
		//and a random location in the room
		x= get_ran(1,get_flag(1,b),get_flag(1,b) + get_flag(3,b) - 1);
		y = get_ran(1,get_flag(2,b),get_flag(2,b) + get_flag(4,b) - 1);
		place_monster(x,y,m,0);
		if((m == 47) || (m == 49)){
			d = (1 + -2 * (get_flag(11,7) > 128)) * (get_flag(11,6) + 256 * (get_flag(11,7) - (128 * (get_flag(11,7) > 128))));
			d = d + 1;
			set_flag(11,6,(1 + -2 * (d < 0)) *d);
			set_flag(11,7,(d / (256 * (1 + -2 * (d < 0)))) + (128 * (d < 0)));
		}
		a = a + 1;
	}
	a=0; //number of non-undead
	b=0; //number of undead
	i=6; //creature number
	while(i<120){
		if((char_ok(i) == 1)){
			if(get_species(i)==8)
				b = b + 1;
			else
				a = a + 1;
		}
		i = i + 1;
	}
	if(b > a){ //if undead outnumber living, they may form their own side
		i = 6;
		while(i<120){
			if((char_ok(i) == 1) && get_species(i)==8)
				set_attitude(i,11);
			i = i + 1;
		}
	}
	set_flag(0,0,15);
break;

beginstate 25; //frill floors in first half of town
	//DEBUGprint_num(25);
	i = 0; //x coordinate
	while(i < 64){
		j = 0; //y coordinate
		while(j < 32){
			if(get_floor(i,j)==4){ //if the point is inside a tunnel or room
				k = get_ran(1,1,40);
				if(k < 8)
					set_floor(i,j,7);
				else if(k < 14)
					set_floor(i,j,5);
				else if(k < 18)
					set_floor(i,j,6);
				else if((k < 19) && (get_terrain(i,j) == 0))
					set_terrain(i,j,166); //place some stalagmites, but don't overwrite anything more important
			}
			j = j + 1;
		}
		i = i + 1;
	}
	set_flag(0,0,16);
break;

beginstate 26; //frill floors in second half of town
	//DEBUGprint_num(26);
	i = 0; //x coordinate
	while(i < 64){
		j = 32; //y coordinate
		while(j < 64){
			if(get_floor(i,j)==4){ //if the point is inside a tunnel or room
				k = get_ran(1,1,40);
				if(k < 8)
					set_floor(i,j,7);
				else if(k < 14)
					set_floor(i,j,5);
				else if(k < 18)
					set_floor(i,j,6);
				else if((k < 19) && (get_terrain(i,j) == 0))
					set_terrain(i,j,166); //place some stalagmites, but don't overwrite anything more important
			}
			j = j + 1;
		}
		i = i + 1;
	}
	set_flag(0,0,17);
break;


beginstate 27; //clean up stains
	//DEBUGprint_num(27);
	i = 0; //location index
	while(i < 3844){ //ignore locations on the edge of the town; monsters are never there
		put_stain_on_space(1 + (i % 62), 1 + (i / 62),-1);
		i = i + 1;
	}
	set_flag(0,0,18);
break;

beginstate 28; //erase old items
	//DEBUGprint_num(28);
	i = 0; //location index
	while(i < 3844){ //items couldn't be dropped at the edges of the town anyway
		move_item_on_spot(1 + (i % 62), 1 + (i / 62),-1,-1);
		i = i + 1;
	}
	set_flag(0,0,19);
break;

beginstate 29; 
	//do nothing on Windows
	set_flag(0,0,20);
break;
	
beginstate 30; //try to find a place for a secret passage
	//DEBUGprint_num(30);
	a = -1; //x coordinate of exit
	b = -1; //y coordinate of exit
	c = 0; //direction of exit, 2=n, 4=w, 8=s, 16=e
	i=1; //room number, skipping first room
	//for each room after the first
	while(i < get_flag(0,1)){
		d = 0; //number of exits found
		//north side
		j = get_flag(1,i); //x coordinate
		while(j < (get_flag(1,i) + get_flag(3,i))){
			if(get_floor(j,get_flag(2,i) - 1)!=255){
				a = j;
				b = get_flag(2,i) - 1;
				c = 2;
				d = d + 1;
			}
			j = j + 1;
		}
		//west side
		if(d < 2){
			j = get_flag(2,i); //y coordinate
			while(j < (get_flag(2,i) + get_flag(4,i))){
				if(get_floor(get_flag(1,i) - 1,j)!=255){
					a = get_flag(1,i) - 1;
					b = j;
					c = 4;
					d = d + 1;
				}
				j = j + 1;
			}
		}
		if(d < 2){
		 	//south side
			j = get_flag(1,i); //x coordinate
			while(j < (get_flag(1,i) + get_flag(3,i))){
				if(get_floor(j,get_flag(2,i) + get_flag(4,n))!=255){
					a = j;
					b = get_flag(2,i) + get_flag(4,n);
					c = 8;
					d = d + 1;
				}
				j = j + 1;
			}
		}
		if(d < 2){
			//east side
			j = get_flag(2,i); //y coordinate
			while(j < (get_flag(2,i) + get_flag(4,i))){
				if(get_floor(get_flag(1,i) + get_flag(3,i),j)!=255){
					a = get_flag(1,i) + get_flag(3,i);
					b = j;
					c = 16;
					d = d + 1;
				}
				j = j + 1;
			}
		}
		if(d==1){ //there was only one exit, so hide it
			//debug output
			clear_buffer();
			append_string("room ");
			append_number(i);
			append_string(" has one exit at (");
			append_number(a);
			append_string(", ");
			append_number(b);
			append_string(") in direction ");
			append_number(c);
			get_buffer_text(str);
			//DEBUGprint_str(str);
			set_flag(0,14,i+1); //number of secret room plus one
			set_state_continue(80);
		}
		i=i +1;
	}
	set_flag(0,0,21);
break;

beginstate 31; //place items
//flag 0,4 is the number of items to place
//the numbers are stored in flags (7,i) and (8,i) (since item numbers may be >255)
	//DEBUGprint_num(31);
	set_flag(0,4,0);
	a = get_flag(0,3) + 1;
	//select items to place
	if(get_ran(1,0,1) == 1){
		//place a defensive item
		b = a - 26;
		if(b < 13)
			b = 13;
		c = a + 35;
		if(c > 109)
			c = 109;
		//skip over blocks of items that must not be changed
		if(b>=84)
			b = b + 5;
		if(b>=99)
			b = b + 10;
		if(c>=84)
			c = c + 5;
		if(c>=99)
			c = c + 10;
		set_flag(7,get_flag(0,4),get_ran(1,b,c));
		set_flag(8,get_flag(0,4),0);
		//DEBUGprint_str("def item");
		//DEBUGprint_num(get_flag(7,get_flag(0,4)));
		inc_flag(0,4,1);
	}
	if(get_ran(1,0,1) == 1){
		//place a weapon
		b = (a / 2) + 104;
		if(b < 110)
			b = 110;
		c = (a / 2) + 121;
		if(c > 180)
			c = 180;
		b = b + 15;
		c = c + 15; //offset like above
		set_flag(7,get_flag(0,4),get_ran(1,b,c));
		set_flag(8,get_flag(0,4),0);
		//DEBUGprint_str("wep item");
		//DEBUGprint_num(get_flag(7,get_flag(0,4)));
		inc_flag(0,4,1);
	}
	if(get_ran(1,0,1) == 1){
		//place a thrown ammo
		d = get_ran(1,446,456);
		set_flag(7,get_flag(0,4), d % 256);
		set_flag(8,get_flag(0,4), d / 256);
		//DEBUGprint_str("thrown item");
		//DEBUGprint_num(get_flag(7,get_flag(0,4)));
		inc_flag(0,4,1);
	}
	if(get_ran(1,0,2) < 2){
		//place a bow ammo
		d = get_ran(1,457,470);
		set_flag(7,get_flag(0,4), d % 256);
		set_flag(8,get_flag(0,4), d / 256);
		//DEBUGprint_str("arrow item");
		//DEBUGprint_num(get_flag(7,get_flag(0,4)));
		inc_flag(0,4,1);
	}
	if(get_ran(1,0,5) == 1){
		//place a ring
		d = get_ran(1,264,281);
		set_flag(7,get_flag(0,4), d % 256);
		set_flag(8,get_flag(0,4), d / 256);
		//DEBUGprint_str("ring item");
		//DEBUGprint_num(d);
		inc_flag(0,4,1);
	}
	if(get_ran(1,0,5) == 1){
		//place a bracelet
		d = get_ran(1,294,301);
		set_flag(7,get_flag(0,4),d % 256);
		set_flag(8,get_flag(0,4),d / 256);
		//DEBUGprint_str("brace item");
		//DEBUGprint_num(d);
		inc_flag(0,4,1);
	}
	if(get_ran(1,0,5) == 1){
		//place a necklace
		d = get_ran(1,302,312);
		set_flag(7, get_flag(0,4), d % 256);
		set_flag(8, get_flag(0,4), d / 256);
		//DEBUGprint_str("neck item");
		//DEBUGprint_num(d);
		inc_flag(0,4,1);
	}
	if(get_ran(1,0,2) == 1){
		//place a potion
		b = 220;
		if((a >= 40) && (a < 80) && (get_ran(1,0,1) == 1))
			b = 228;
		if(a >= 80)
			b = 228;
		set_flag(7,get_flag(0,4),get_ran(1,b,b+5));
		set_flag(8,get_flag(0,4),0);
		//DEBUGprint_str("pot. item");
		//DEBUGprint_num(get_flag(7,get_flag(0,4)));
		inc_flag(0,4,1);
	}
	if(get_ran(1,0,4) == 1){
		//place a scroll
		d = get_ran(1,244,261);
		set_flag(7,get_flag(0,4),d);
		set_flag(8,get_flag(0,4),d / 256);
		//DEBUGprint_str("scroll item");
		//DEBUGprint_num(d);
		inc_flag(0,4,1);
	}
	if(get_ran(1,0,4) == 1){
		//place a wand
		b = get_ran(1,1,33);
		if(b <= 5)
			c = 0;
		else if(b <= 9)
			c = 1;
		else if(b <= 12)
			c = 2;
		else if(b <= 16)
			c = 3;
		else if(b <= 19)
			c = 4;
		else if(b <= 23)
			c = 5;
		else if(b <= 24)
			c = 6;
		else if(b <= 25)
			c = 7;
		else if(b <= 26)
			c = 8;
		else if(b <= 29)
			c = 9;
		else if(b <= 31)
			c = 10;
		else
			c = 11;
		set_flag(7,get_flag(0,4),c + 282);
		set_flag(8,get_flag(0,4),(c + 282) / 256);
		//DEBUGprint_str("wand item");
		//DEBUGprint_num(c + 282);
		inc_flag(0,4,1);
	}
	if(get_ran(1,0,3) == 1){
		//place a teaching scroll
		b = ((a + 10) / 6) + 462;
		c = b + 10;
		if(b < 472)
			b = 472;
		if(c > 492)
			c = 492;
		d = get_ran(1,b,c);
		//don't give out a fourth scroll of this type if there's still
		//a type of which we've given out less than 3
		if(get_flag(9,d - 472) >= 3){
			x = d;
			d = d + 1;
			if(d>492)
				d = 472;
			while((d != x) && (get_flag(9,d - 472) >= 3)){
				d = d + 1;
				if(d>492)
					d = 472;
			}
		}
		set_flag(7,get_flag(0,4), d % 256);
		set_flag(8,get_flag(0,4), d / 256);
		inc_flag(9,d - 472,1);
		//DEBUGprint_str("teach item");
		//DEBUGprint_num(get_flag(7,get_flag(0,4)));
		inc_flag(0,4,1);
	}
	if(get_ran(1,0,3) == 1){
		//place an identification scroll
		d = 493;
		set_flag(7,get_flag(0,4), d % 256);
		set_flag(8,get_flag(0,4), d / 256);
		//DEBUGprint_str("ident item");
		//DEBUGprint_num(get_flag(7,get_flag(0,4)));
		inc_flag(0,4,1);
	}
	if(get_ran(1,0,1) == 1){
		//place a rock
		set_flag(7,get_flag(0,4), 446 % 256);
		set_flag(8,get_flag(0,4), 446 / 256);
		//DEBUGprint_str("rock");
		//DEBUGprint_num(get_flag(7,get_flag(0,4)));
		inc_flag(0,4,1);
	}
	if(get_flag(0,3) == 0){ //place lucky crystal
		//DEBUGprint_str("lucky");
		set_flag(7,get_flag(0,4), 496 % 256);
		set_flag(8,get_flag(0,4), 496 / 256);
		inc_flag(0,4,1);
	}
	//actually place all of the items selected above
	a = 0;
	while(a < get_flag(0,4)){
		b = get_ran(1,0,get_flag(0,1) - 1); //choose a random room to put the item in
		if(get_flag(0,14)>0){ //if there is a secret room
			if(get_ran(1,1,10) == 1){ //10% chance
				b = get_flag(0,14) - 1; //of putting each item there
			}
		}
		//and a random location in the room
		x= get_ran(1,get_flag(1,b),get_flag(1,b) + get_flag(3,b) - 1);
		y = get_ran(1,get_flag(2,b),get_flag(2,b) + get_flag(4,b) - 1);
		put_item_on_spot(x,y,get_flag(7,a) + (256 * get_flag(8,a)));
		a = a + 1;
	}
	set_flag(0,0,22);
break;

beginstate 32; //place traps and pools
	//DEBUGprint_num(32);
	i = 0;
	k = 10;
	while(i < 8){
		if(get_ran(1,1,5) == 1 || get_flag(0,3) == 119){ //place an object
			j = 0;
			while(j < k){ //make a maximum of k tries
				b = get_ran(1,0,get_flag(0,1) - 1); //choose a random room to put the object in
				//and a random location in the room
				x= get_ran(1,get_flag(1,b),get_flag(1,b) + get_flag(3,b) - 1);
				y = get_ran(1,get_flag(2,b),get_flag(2,b) + get_flag(4,b) - 1);
				if(i < 4 && get_terrain(x,y) == 0 && (get_floor(x,y) >= 4) && (get_floor(x,y) <= 7)){
					set_terrain(x,y,436 + i);
					set_flag(10,i,1);
					//DEBUGprint_str("pool");
					j = 2 * k;
					//increment total number of pools placed
					c = (1 + -2 * (get_flag(11,11) > 128)) * (get_flag(11,10) + 256 * (get_flag(11,11) - (128 * (get_flag(11,11) > 128))));
					c = c + 1;
					set_flag(11,10,(1 + -2 * (c < 0)) * c);
					set_flag(11,11,(c / (256 * (1 + -2 * (c < 0)))) + (128 * (c < 0)));
				}
				else if((i >= 4) && (get_floor(x,y) >= 4) && (get_floor(x,y) <= 7)){
					set_floor(x,y,132 + i - 4);
					set_flag(10,i,1);
					//DEBUGprint_str("trap");
					j = 2 * k;
					//increment total number of traps placed
					c = (1 + -2 * (get_flag(11,1) > 128)) * (get_flag(11,0) + 256 * (get_flag(11,1) - (128 * (get_flag(11,1) > 128))));
					c = c + 1;
					set_flag(11,0,(1 + -2 * (c < 0)) * c);
					set_flag(11,1,(c / (256 * (1 + -2 * (c < 0)))) + (128 * (c < 0)));
				}
				j = j + 1;
			}
		}
		i = i + 1;
	}
	set_flag(0,0,23);
break;

beginstate 33; //move the player into the level proper and do final cleanup operations
	if(get_flag(0,3) == 119)
		set_state_continue(92);
	//DEBUGprint_num(33);
	//a random location in room 0
	x = get_ran(1,get_flag(1,0),get_flag(1,0) + get_flag(3,0) - 1);
	y = get_ran(1,get_flag(2,0),get_flag(2,0) + get_flag(4,0) - 1);
	if(char_on_spot(x,y) > -1){ //there's a monster standing there, so we need to find a different space
		i = 0;
		j = get_flag(3,0) * get_flag(4,0); //the number of spaces in the room
		k = (x - get_flag(1,0)) + ((y - get_flag(2,0)) * get_flag(4,0));
		while((i < j) && (char_on_spot(x,y) != -1)){
			k = k + 1; //advance to the next space
			if(k >= j)
				k = 0; //wrap around to NW corner of room
			x = (k % get_flag(3,0)) + get_flag(1,0);
			y = (k / get_flag(3,0)) + get_flag(2,0);
			i = i + 1;
		}
	}
	//move the player to the selected location
	teleport_party(x,y,1);
	//disallow training until everything has been killed
	turn_off_training(1);
	set_flag(0,3,get_flag(0,3) + 1);//increment the number of levels entered
	clear_buffer();
	append_string("Entering level ");
	append_number(get_flag(0,3));
	get_buffer_text(str);
	print_str_color(str,4);
	set_flag(0,0,24);
break;

beginstate 80; //conceal the entrance to a room behind a secret door
	//DEBUGprint_num(80);
	if(get_ran(1,0,120) > get_flag(0,3)){
		//only actually put in the secret door with a probability
		//proportional to the level number over 120 so that
		//secret passages are less likely on earlier levels
		//DEBUGprint_str("cancelled passage");
		set_flag(0,14,0); //unset secret room number
		set_flag(0,0,21);
		end();
	}
	i = 0; //number of units of passage traversed
	while(i < 200){ //just don't go on forever
		i = i + 1;
		d = 0; //the direction of the next move
		if(c != 2){ //if we didn't enter from the south, try to move south
			if(get_floor(a,b + 1)!=255)
				d = d + 8; //the path is clear to the south
		}
		if(c != 4){ //try to move east
			if(get_floor(a + 1,b)!=255)
				d = d + 16; //the path is clear to the east
		}
		if(c != 8){ //try to move north
			if(get_floor(a,b - 1)!=255)
				d = d + 2; //the path is clear to the north
		}
		if(c != 16){ //try to move east
			if(get_floor(a - 1,b)!=255)
				d = d + 4; //the path is clear to the east
		}
		if(d!=2 && d!=4 && d!=8 && d!=16) //there was move than one way to continue
			i = 5280; //break out of the loop with special code
		else{ //advance along the passage
			c = d; //update the direction moved
			if(c==2) //move north
				b = b - 1;
			else if (c==4) //move west
				a = a - 1;
			else if(c==8) //move south
				b = b + 1;
			else if(c==16) //move east
				a = a + 1;
			clear_buffer();
			append_string("advanced to ");
			append_number(i);
			append_string(" (");
			append_number(a);
			append_string(", ");
			append_number(b);
			append_string(") in direction ");
			append_number(c);
			get_buffer_text(str);
			//DEBUGprint_str(str);
		}
	}
	if(i == 5280){ //the passage reached a branching point
		//backtrack and place the secret door
		if(c==2){
			if(get_terrain(a,b + 1) == 284){
				//abort! We mustn't overwrite the trapdoor. 
				set_flag(0,14,0); //unset secret room number
				set_flag(0,0,21);
				end();
			}
			else{
				set_terrain(a,b + 1,18);
				set_flag(0,8,a - 1);
				set_flag(0,9,b + 1);
				set_flag(0,10,get_terrain(a - 1,b + 1) - 420);
				set_flag(0,11,a + 1);
				set_flag(0,12,b + 1);
				set_flag(0,13,get_terrain(a + 1,b + 1) - 420);
				m = get_terrain(a - 1,b + 1) - 420;
				if(((m / 2) % 2) ==1)
					m = m - 2;
				if(m == 0)
					set_terrain(a - 1, b + 1, 407);
				else
					set_terrain(a - 1, b + 1, m + 420);
				m = get_terrain(a + 1,b + 1) - 420;
				if(((m / 8) % 2) ==1)
					m = m - 8;
				if(m == 0)
					set_terrain(a + 1, b + 1, 407);
				else
					set_terrain(a + 1, b + 1, m + 420);
			}
		}
		else if(c==4){
			if(get_terrain(a + 1,b) == 284){
				//abort! We mustn't overwrite the trapdoor. 
				set_flag(0,14,0); //unset secret room number
				set_flag(0,0,21);
				end();
			}
			else{
				set_terrain(a + 1,b,19);
				set_flag(0,8,a + 1);
				set_flag(0,9,b - 1);
				set_flag(0,10,get_terrain(a + 1,b - 1) - 420);
				set_flag(0,11,a + 1);
				set_flag(0,12,b + 1);
				set_flag(0,13,get_terrain(a + 1,b + 1) - 420);
				m = get_terrain(a + 1,b - 1) - 420;
				if(((m / 4) % 2) ==1)
					m = m - 4;
				if(m == 0)
					set_terrain(a + 1, b - 1, 407);
				else
					set_terrain(a + 1, b - 1, m + 420);
				m = get_terrain(a + 1,b + 1) - 420;
				if((m % 2) ==1)
					m = m - 1;
				if(m == 0)
					set_terrain(a + 1, b + 1, 407);
				else
					set_terrain(a + 1, b + 1, m + 420);
			}
		}
		else if(c==8){
			if(get_terrain(a,b - 1) == 284){
				//abort! We mustn't overwrite the trapdoor. 
				set_flag(0,14,0); //unset secret room number
				set_flag(0,0,21);
				end();
			}
			else{
				set_terrain(a,b - 1,20);
				set_flag(0,8,a - 1);
				set_flag(0,9,b - 1);
				set_flag(0,10,get_terrain(a - 1,b - 1) - 420);
				set_flag(0,11,a + 1);
				set_flag(0,12,b - 1);
				set_flag(0,13,get_terrain(a + 1,b - 1) - 420);
				m = get_terrain(a - 1,b - 1) - 420;
				if(((m / 2) % 2) ==1)
					m = m - 2;
				if(m == 0)
					set_terrain(a - 1, b - 1, 407);
				else
					set_terrain(a - 1, b - 1, m + 420);
				m = get_terrain(a + 1,b - 1) - 420;
				if(((m / 8) % 2) ==1)
					m = m - 8;
				if(m == 0)
					set_terrain(a + 1, b - 1, 407);
				else
					set_terrain(a + 1, b - 1, m + 420);
			}
		}
		else if(c==16){
			if(get_terrain(a,b + 1) == 284){
				//abort! We mustn't overwrite the trapdoor. 
				set_flag(0,14,0); //unset secret room number
				set_flag(0,0,21);
				end();
			}
			else{
				set_terrain(a - 1,b,21);
				set_flag(0,8,a - 1);
				set_flag(0,9,b - 1);
				set_flag(0,10,get_terrain(a - 1,b - 1) - 420);
				set_flag(0,11,a - 1);
				set_flag(0,12,b + 1);
				set_flag(0,13,get_terrain(a - 1,b + 1) - 420);
				m = get_terrain(a - 1,b - 1) - 420;
				if(((m / 4) % 2) ==1)
					m = m - 4;
				if(m == 0)
					set_terrain(a - 1, b - 1, 407);
				else
					set_terrain(a - 1, b - 1, m + 420);
				m = get_terrain(a - 1,b + 1) - 420;
				if((m % 2) ==1)
					m = m - 1;
				if(m == 0)
					set_terrain(a - 1, b + 1, 407);
				else
					set_terrain(a - 1, b + 1, m + 420);
			}
		}
		//increment number of passages placed
		inc_flag(11,4,1);
		//note that there is a passage on this level
		set_flag(10,9,1);
	}
	set_flag(0,0,21);
break;

beginstate 90; //draw room rectangles for final level
//rooms are stored in flag columns 1-4
//room n upper left x is in flag (1,n)
//upper left y is in (2,n)
//width is in (3,n)
//height is in (4,n)
	//DEBUGprint_num(90);
	set_flag(0,1,8); //8 rooms
	
	set_flag(1,0,5);
	set_flag(2,0,5);
	set_flag(3,0,5);
	set_flag(4,0,5);
	
	set_flag(1,1,7);
	set_flag(2,1,29);
	set_flag(3,1,10);
	set_flag(4,1,9);
	
	set_flag(1,2,14);
	set_flag(2,2,54);
	set_flag(3,2,8);
	set_flag(4,2,8);
	
	set_flag(1,3,44);
	set_flag(2,3,46);
	set_flag(3,3,8);
	set_flag(4,3,9);
	
	set_flag(1,4,54);
	set_flag(2,4,25);
	set_flag(3,4,8);
	set_flag(4,4,9);
	
	set_flag(1,5,50);
	set_flag(2,5,5);
	set_flag(3,5,5);
	set_flag(4,5,5);
	
	set_flag(1,6,23);
	set_flag(2,6,10);
	set_flag(3,6,13);
	set_flag(4,6,8);
	
	set_flag(1,7,25);
	set_flag(2,7,25);
	set_flag(3,7,15);
	set_flag(4,7,15);

	set_flag(0,0,4);
break;

beginstate 91; //place monsters for final level
	//DEBUGprint_num(91);

	place_monster(14,32,71,0);
	place_monster(11,33,74,0);

	place_monster(16,58,72,0);

	place_monster(46,48,69,0);
	place_monster(48,52,69,0);
	place_monster(49,48,69,0);

	place_monster(56,29,68,0);
	place_monster(59,29,68,0);

	place_monster(31,12,73,0);
	place_monster(31,15,73,0);
	place_monster(27,14,72,0);
	
	place_monster(32,31,75,0);

	i=6; //creature number
	while(i < 120){
		if(creature_type(i) == 75){//make the doomguard stand still
			set_creature_memory_cell(i,0,1);
			i = 1000;	
		}
		i=i +1;
	}
	set_flag(0,0,15);
break;

beginstate 92; //finishing up state for final level
	//DEBUGprint_num(92);

	set_terrain(32,32,218);
	put_item_on_spot(32,32,445);

	teleport_party(7,7,1);
	inc_flag(0,3,1);//increment the number of levels entered
	clear_buffer();
	append_string("Entering level ");
	append_number(get_flag(0,3));
	get_buffer_text(str);
	print_str_color(str,4);
	print_str_color("Good luck",4);
	set_flag(0,0,24);
break;

beginstate 98; //ending the game
	//take away items that the game would remove anyway
	take_all_of_item(288);
	take_all_of_item(316);
	take_all_of_item(317);
	take_all_of_item(318);
	take_all_of_item(496);
	i = 472;
	while(i < 494){
		take_all_of_item(i);
		i = i + 1;
	}
	k = has_num_of_item(446);
	take_all_of_item(446);
	x = (1 + -2 * (get_flag(11,3) > 128)) * (get_flag(11,2) + 256 * (get_flag(11,3) - (128 * (get_flag(11,3) > 128))));
	y = (1 + -2 * (get_flag(11,1) > 128)) * (get_flag(11,0) + 256 * (get_flag(11,1) - (128 * (get_flag(11,1) > 128))));
	if(y > 0)
		m = (100 * x) / y;
	else
		m = 0;
	//DEBUGprint_nums(x,y,m);
	if(m >= 10)
		reward_give(372);
	x = get_flag(11,5);
	y = get_flag(11,4);
	if(y > 0)
		m = (100 * x) / y;
	else
		m = 0;
	//DEBUGprint_nums(x,y,m);
	x = (1 + -2 * (get_flag(11,9) > 128)) * (get_flag(11,8) + 256 * (get_flag(11,9) - (128 * (get_flag(11,9) > 128))));
	y = (1 + -2 * (get_flag(11,7) > 128)) * (get_flag(11,6) + 256 * (get_flag(11,7) - (128 * (get_flag(11,7) > 128))));
	//DEBUGprint_nums(x,y,x == y);
	if((x > 0) && (x == y))
		reward_give(374);
	x = (1 + -2 * (get_flag(11,13) > 128)) * (get_flag(11,12) + 256 * (get_flag(11,13) - (128 * (get_flag(11,13) > 128))));
	y = (1 + -2 * (get_flag(11,11) > 128)) * (get_flag(11,10) + 256 * (get_flag(11,11) - (128 * (get_flag(11,11) > 128))));
	if(y>0)
		m = (68 * x) / y;
	else
		m = 0;
	//DEBUGprint_nums(x,y,x == y);
	if(m > 64)
		reward_give(375);
	if((k + has_num_of_item(456)) >= 10){
		reward_give(376);
	}
	reset_dialog();
	add_dialog_str(0,"Finally, you have the fabled Amulet of Yendor in your hands, and your every enemy is destroyed. ",0);
	add_dialog_str(1,"As you pause to consider the completeness of your victory, the amulet begins to glow. With a sudden blast of magic, you find yourself back aboveground. ",0);
	add_dialog_str(2,"THE END",0);
	add_dialog_choice(0,"OK");
	run_dialog(1);
	end_scenario(1);
break;

beginstate 99; //trap door
	if(group_dist_to_loc(0,get_flag(5,get_flag(0,2)),get_flag(6,get_flag(0,2))) > 2)
		end(); //only let the player descend if this exit point is blessed
	reset_dialog_preset_options(9);
	a = run_dialog(0);
	if(a == 1)
		end();
	set_flag(0,0,1);
	//recharge all energy and 1/10th of health
	restore_energy_char(0,1000);
	heal_char(0,get_max_health(0)/10);
	//reset pools and traps
	set_flag(10,0,0);
	set_flag(10,1,0);
	set_flag(10,2,0);
	set_flag(10,3,0);
	set_flag(10,4,0);
	set_flag(10,5,0);
	set_flag(10,6,0);
	set_flag(10,7,0);
	set_flag(10,8,0);
	set_flag(10,9,0);
	//put the player in the corner while the next town is generated
	move_to_new_town(0,63,63);
break;